package com.jacky.path_provider_ex;

import static android.app.Activity.RESULT_OK;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.Settings;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;

import com.jacky.JAlertDialog;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class FilePermissionHandler {

    interface OnPermissionCallback {

        void onSuccess();

        void onFail(String code, String message);
    }

    private final Activity activity;
    private final String[] permissions;
    private static final int CODE_REQUEST_STORAGE = 3000;
    private static final int CODE_REQUEST_ALL_FILE_ACCESS = 3001;
    private static final int APK_CODE = 3002;
    private String apkPath;
    private final List<OnPermissionCallback> onPermissionCallbacks = new ArrayList<>();
    private boolean lock = false;
    private static final String ERROR_CODE = "-10004";

    public FilePermissionHandler(Activity activity) {
        this.activity = activity;
        permissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
    }

    public void requestPermissions(String[] permissions, int requestCode) {
        ActivityCompat.requestPermissions(activity, permissions, requestCode);
    }

    public void startActivityForResult(Intent intent, int code) {
        activity.startActivityForResult(intent, code);
    }

    @UiThread
    public void request(OnPermissionCallback onPermissionCallback) {
        onPermissionCallbacks.add(onPermissionCallback);
        if (lock) {
            return;
        }
        lock = true;
        if (shouldRequestPhonePermission()) {
            requestPermissions(permissions, CODE_REQUEST_STORAGE);
            return;
        }
        if (shouldRequestAllFileAccessPermission()) {
            showRequestAllFileAccessPermissionDialog();
            return;
        }
        notifySuccess();
    }

    public boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (requestCode == CODE_REQUEST_STORAGE) {
            if (shouldRequestPhonePermission()) {
                notifyError(ERROR_CODE, "用户未授权存储管理权限");
            } else {
                if (shouldRequestAllFileAccessPermission()) {
                    showRequestAllFileAccessPermissionDialog();
                } else {
                    notifySuccess();
                }
            }
            return true;
        } else if (requestCode == CODE_REQUEST_ALL_FILE_ACCESS) {
            if (shouldRequestAllFileAccessPermission()) {
                notifyError(ERROR_CODE, "用户未授权文件管理权限");
            } else {
                notifySuccess();
            }
            return true;
        } else if(resultCode == RESULT_OK && requestCode == APK_CODE) {
            installApk(apkPath);
            return true;
        }
        return false;
    }

    public boolean onRequestPermissionsResult(int requestCode,
                                              @NonNull String[] permissions,
                                              @NonNull int[] grantResults) {
        if (requestCode == CODE_REQUEST_STORAGE) {
            if (isPermissionOK(grantResults)) {
                if (shouldRequestAllFileAccessPermission()) {
                    showRequestAllFileAccessPermissionDialog();
                } else {
                    notifySuccess();
                }
            } else {
                new JAlertDialog()
                        .setTitle("温馨提示")
                        .setMessage("存储权限被拒绝")
                        .setCancelable(false)
                        .setBtnOk("设置", (dialog, which) -> {
                            dialog.dismiss();
                            Intent settingsIntent = new Intent();
                            settingsIntent.setAction(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                            settingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
                            settingsIntent.setData(android.net.Uri.parse("package:" + activity.getPackageName()));
                            settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                            settingsIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                            startActivityForResult(settingsIntent, CODE_REQUEST_STORAGE);
                        }).setBtnCancel("取消", (dialog, which) -> {
                            dialog.dismiss();
                            notifyError(ERROR_CODE, "用户取消手动申请存储权限");
                        })
                        .show(activity);
            }
            return true;
        }
        return false;
    }


    public boolean shouldRequestPhonePermission() {
        return !isPermissionsGranted(activity, permissions);
    }

    private boolean shouldRequestAllFileAccessPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            return !Environment.isExternalStorageManager();
        }
        return false;
    }

    private void showRequestAllFileAccessPermissionDialog() {
        new JAlertDialog()
                .setTitle("温馨提示")
                .setMessage("是否启用文件管理权限？")
                .setCancelable(false)
                .setBtnOk("确定", (dialog, which) -> {
                    dialog.dismiss();
                    @SuppressLint("InlinedApi") Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
                    intent.setData(Uri.parse("package:" + activity.getPackageName()));
                    startActivityForResult(intent, CODE_REQUEST_ALL_FILE_ACCESS);
                }).
                setBtnCancel("取消", (dialog, which) -> {
                    dialog.dismiss();
                    notifyError(ERROR_CODE, "用户取消手动启用文件管理权限");
                })
                .show(activity);
    }

    public void notifyError(String code, String message) {
        for (OnPermissionCallback onPermissionCallback : onPermissionCallbacks) {
            onPermissionCallback.onFail(code, message);
        }
        onPermissionCallbacks.clear();
        lock = false;
    }

    public void notifySuccess() {
        for (OnPermissionCallback onPermissionCallback : onPermissionCallbacks) {
            onPermissionCallback.onSuccess();
        }
        onPermissionCallbacks.clear();
        lock = false;
    }


    private static boolean isPermissionsGranted(Context context, String... permissions) {
        if (permissions.length == 0) {
            return false;
        }
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    private static boolean isPermissionOK(int[] grantResults) {
        for (int i : grantResults) {
            if (i == PackageManager.PERMISSION_DENIED) {
                return false;
            }
        }
        return true;
    }

    public void installApp(String path) {
        if(TextUtils.isEmpty(path)) return;
        apkPath = path;

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            boolean has = activity.getPackageManager().canRequestPackageInstalls();
            if(has) {
                installApk(apkPath);
            } else {
                Uri uri = Uri.parse("package:" + activity.getPackageName());
                Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
                intent.setData(uri);
                startActivityForResult(intent, APK_CODE);
            }
        } else {
            installApk(apkPath);
        }
    }

    private void installApk(String file) {
        Intent intent;
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
        } else {
            intent = new Intent(Intent.ACTION_VIEW);
        }
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
        intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
//        intent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,getPackageName());
        intent.setDataAndType(fromFile(activity, intent, new File(file)),
                "application/vnd.android.package-archive");
        startActivityForResult(intent, -1);
        activity.finish();
    }

    private Uri fromFile(Context context, Intent intent, File file) {
        Uri data;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            data = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file);
            if(intent != null) {
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            }
        } else {
            data = Uri.fromFile(file);
        }
        return data;
    }

}
